package com.gzc.just.play.last.war.common.serializer;

import com.google.protobuf.MessageLite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Method;
import java.util.zip.GZIPInputStream;

/**
 * 通用Protobuf消息反序列化器
 * 
 * 这是一个完全通用的反序列化器，可以处理任何Protobuf消息类型。
 * 通过配置而非继承来指定行为，实现了真正的高内聚低耦合。
 * 
 * 使用方式：
 * 1. 直接通过构造函数创建实例
 * 2. 或通过 DeserializerRegistry 自动从注解创建
 * 
 * 优点：
 * - 无需为每个消息类型创建单独的反序列化器类
 * - 添加压缩/加密等功能只需修改此类
 * - 配置驱动，易于扩展
 * 
 * @param <T> Protobuf消息类型
 */
public class GenericProtobufDeserializer<T extends MessageLite> implements MessageDeserializer<T> {
    
    private static final Logger logger = LoggerFactory.getLogger(GenericProtobufDeserializer.class);
    
    private final Class<T> messageClass;
    private final int messageId;
    private final String module;
    private final Method parseFromMethod;
    
    // 可配置的处理选项
    private final DeserializeOptions options;
    
    /**
     * 反序列化选项配置
     */
    public static class DeserializeOptions {
        private boolean compressionEnabled = false;
        private boolean encryptionEnabled = false;
        private String compressionType = "gzip";
        private String encryptionType = "none";
        private byte[] encryptionKey = null;
        
        public static DeserializeOptions defaults() {
            return new DeserializeOptions();
        }
        
        public DeserializeOptions withCompression(boolean enabled) {
            this.compressionEnabled = enabled;
            return this;
        }
        
        public DeserializeOptions withCompression(String type) {
            this.compressionEnabled = true;
            this.compressionType = type;
            return this;
        }
        
        public DeserializeOptions withEncryption(boolean enabled) {
            this.encryptionEnabled = enabled;
            return this;
        }
        
        public DeserializeOptions withEncryption(String type, byte[] key) {
            this.encryptionEnabled = true;
            this.encryptionType = type;
            this.encryptionKey = key;
            return this;
        }
        
        public boolean isCompressionEnabled() { return compressionEnabled; }
        public boolean isEncryptionEnabled() { return encryptionEnabled; }
        public String getCompressionType() { return compressionType; }
        public String getEncryptionType() { return encryptionType; }
        public byte[] getEncryptionKey() { return encryptionKey; }
    }
    
    /**
     * 简单构造函数
     */
    public GenericProtobufDeserializer(Class<T> messageClass, int messageId) {
        this(messageClass, messageId, "", DeserializeOptions.defaults());
    }
    
    /**
     * 带模块的构造函数
     */
    public GenericProtobufDeserializer(Class<T> messageClass, int messageId, String module) {
        this(messageClass, messageId, module, DeserializeOptions.defaults());
    }
    
    /**
     * 完整构造函数
     */
    public GenericProtobufDeserializer(Class<T> messageClass, int messageId, String module, DeserializeOptions options) {
        this.messageClass = messageClass;
        this.messageId = messageId;
        this.module = module;
        this.options = options != null ? options : DeserializeOptions.defaults();
        this.parseFromMethod = resolveParseFromMethod(messageClass);
    }
    
    /**
     * 通过反射获取Protobuf的parseFrom静态方法
     */
    private Method resolveParseFromMethod(Class<T> clazz) {
        try {
            return clazz.getMethod("parseFrom", byte[].class);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Class " + clazz.getName() + " does not have parseFrom(byte[]) method", e);
        }
    }
    
    @Override
    public T deserialize(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            logger.warn("Cannot deserialize null or empty bytes for {}", messageClass.getSimpleName());
            return null;
        }
        
        try {
            byte[] processedBytes = bytes;
            
            // Step 1: 解密（如果启用）
            if (options.isEncryptionEnabled()) {
                processedBytes = decrypt(processedBytes);
            }
            
            // Step 2: 解压缩（如果启用）
            if (options.isCompressionEnabled()) {
                processedBytes = decompress(processedBytes);
            }
            
            // Step 3: Protobuf解析
            return parseProtobuf(processedBytes);
            
        } catch (Exception e) {
            logger.error("Failed to deserialize {} message (id={}): {}", 
                        messageClass.getSimpleName(), messageId, e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 解密数据
     */
    private byte[] decrypt(byte[] encryptedBytes) throws Exception {
        String type = options.getEncryptionType();
        switch (type.toLowerCase()) {
            case "xor":
                return xorDecrypt(encryptedBytes, options.getEncryptionKey());
            case "aes":
                return aesDecrypt(encryptedBytes, options.getEncryptionKey());
            case "none":
            default:
                return encryptedBytes;
        }
    }
    
    /**
     * XOR解密（简单示例）
     */
    private byte[] xorDecrypt(byte[] data, byte[] key) {
        if (key == null || key.length == 0) {
            return data;
        }
        byte[] result = new byte[data.length];
        for (int i = 0; i < data.length; i++) {
            result[i] = (byte) (data[i] ^ key[i % key.length]);
        }
        return result;
    }
    
    /**
     * AES解密（占位实现，实际使用时需要完善）
     */
    private byte[] aesDecrypt(byte[] data, byte[] key) throws Exception {
        // TODO: 实现AES解密
        // 可以使用 javax.crypto.Cipher
        logger.warn("AES decryption not implemented yet, returning raw data");
        return data;
    }
    
    /**
     * 解压缩数据
     */
    private byte[] decompress(byte[] compressedBytes) throws Exception {
        String type = options.getCompressionType();
        switch (type.toLowerCase()) {
            case "gzip":
                return gzipDecompress(compressedBytes);
            case "lz4":
                return lz4Decompress(compressedBytes);
            case "snappy":
                return snappyDecompress(compressedBytes);
            case "none":
            default:
                return compressedBytes;
        }
    }
    
    /**
     * GZIP解压缩
     */
    private byte[] gzipDecompress(byte[] compressedBytes) throws Exception {
        try (ByteArrayInputStream bis = new ByteArrayInputStream(compressedBytes);
             GZIPInputStream gis = new GZIPInputStream(bis);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            
            byte[] buffer = new byte[1024];
            int len;
            while ((len = gis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        }
    }
    
    /**
     * LZ4解压缩（占位实现）
     */
    private byte[] lz4Decompress(byte[] data) throws Exception {
        // TODO: 实现LZ4解压缩
        logger.warn("LZ4 decompression not implemented yet, returning raw data");
        return data;
    }
    
    /**
     * Snappy解压缩（占位实现）
     */
    private byte[] snappyDecompress(byte[] data) throws Exception {
        // TODO: 实现Snappy解压缩
        logger.warn("Snappy decompression not implemented yet, returning raw data");
        return data;
    }
    
    /**
     * 解析Protobuf消息
     */
    @SuppressWarnings("unchecked")
    private T parseProtobuf(byte[] bytes) throws Exception {
        return (T) parseFromMethod.invoke(null, bytes);
    }
    
    // Getters
    public Class<T> getMessageClass() { return messageClass; }
    public int getMessageId() { return messageId; }
    public String getModule() { return module; }
    public DeserializeOptions getOptions() { return options; }
}
